package com.sparrow.common.hotswap;

import com.sparrow.common.thread.factory.SimpleThreadFactory;
import com.sparrow.common.util.PropertiesUtil;
import com.sparrow.common.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;

/**
 * 热更Class调度检查
 */
@Component
public class HotSwapService implements DisposableBean {
    private static final Logger logger = LoggerFactory.getLogger(HotSwapService.class);

    private static String hotSwapDir = PropertiesUtil.autoReloadString("hotswap.dir", (val) -> hotSwapDir = val, null);

    private static String agentPath = PropertiesUtil.autoReloadString("agent.path", (val) -> agentPath = val, null);

    private static final Map<Path, Long> fileModifyCache = new HashMap<>();

    private ScheduledExecutorService scheduledExecutor;

    private HotSwapManager hotSwapManager;

    @PostConstruct
    public void init() {
        if (StringUtil.isNotEmpty(hotSwapDir) && StringUtil.isNotEmpty(agentPath)) {
            this.hotSwapManager = new HotSwapManager(hotSwapDir, agentPath);
        }

        ScheduledExecutorService scheduledExecutor = Executors.newSingleThreadScheduledExecutor(new SimpleThreadFactory("HotSwap"));
        scheduledExecutor.scheduleWithFixedDelay(() -> {
            try {
                hotSwap();
            } catch (Throwable t) {
                logger.error("hotSwap err", t);
            }
        }, 10, 10, TimeUnit.SECONDS);
    }

    public void hotSwap() {
        if (hotSwapManager != null) {
            hotSwapManager.tryRedefineClass();
        }
    }

    @Override
    public void destroy() throws Exception {
        if (scheduledExecutor != null) {
            scheduledExecutor.shutdown();
        }
        logger.info("HotSwapService关闭");
    }
}
